/* Janus Chat - Version 1.0
 * Authors: Matthew Perry
 *          Michael Freid
 *          Marc Latou
 *          Richard Lee
 *
 * The Janus Chat Client is a highly secured
 * peer-to-peer chat client designed to facilitate
 * the transfer of sensitive data or as a communication
 * medium for the extra paranoid
 *
 * This file contains the header for a Message class. 
 * This class will serve as the main packet encapsulation
 * for janus' communications */
#ifndef MESSAGE_H
#define MESSAGE_H
#define MSG_SIZE 1048

#include <vector>
#include <string>
#include "jRsa.h"
#include "jAes.h"

using std::string;
using std::vector;

class Message
{
    private:
        unsigned int myType;     /* Type number of this message */
        unsigned int myFieldSize;/* Current total size of all field elements */
        vector<string> myFields; /* Data fields in the body */
        string myBody;           /* The body of the message */
        unsigned int myBodyLen;  /* Length of body data */

        /* Helper Functions */
        char* encoder( unsigned int type, const string& body );
        void bodyInit();    /* Turns fields into a body */
        void fieldInit();   /* Turns body into fields */

    public:
        enum Types {
            CryptStandard,
            DecryptStandard,
            PublicKeyExchange,
            SessionKeyExchange,
            ServerInfo,
            ServerData,
            ServerRequest
        };
        const static unsigned int MAX_SIZE = MSG_SIZE;
        const static unsigned int MONIKER_SIZE = 25;
        const static unsigned int BODY_SIZE = MSG_SIZE - 48;
        // Session key exchange is done through static functions because RSA encryption
        // Needs to be used here and ONLY here.
        static Message SessionKeyMessage( const string& key, jRsa::publicKey pk );
        static string SessionKeyRestore( const Message& msg, jRsa::privateKey pk );

        Message( unsigned int type ); /* Constructor for just the type when you have fields */
        Message( unsigned int type, const string& body );   /* Constructor for type and body when you have a field string */
        Message( char* data, unsigned int length );  /* Construct a message given a c-string with a known length */
        ~Message() {}

        char* toChar();   /* Encode this message simply into one c-string */
        char* aesEncrypt( const string& key ); /* Encrypt this message given a key */
        Message aesDecrypt( const string& key ) const; /* Return the decrypted version of this message */

        void addField( const string& str );     /* Add a field to the field list */
        unsigned int getType() const { return myType; }
        string getBody() const { return myBody; }
        string getField( int x ) const { return myFields[x]; }

        string operator[]( int x ) const { return myFields[x]; }
};

#endif
